﻿--[[
全局的基本函数
--]]

-- 定义一个新的类
-- anyTableOrNil：待定义的类，可以传nil
-- return: 一个新类
function DefineClass(anyTableOrNil)
    anyTableOrNil = anyTableOrNil or { };
    anyTableOrNil.__index = anyTableOrNil;
    return anyTableOrNil;
end

-- 派生出新类的工具函数
-- BaseClass: 基类
-- SubClass: 子类，可以填nil
-- return: 返回继承自BaseClass的子类
function DeriveClass(BaseClass, SubClass)
    SubClass = SubClass or { };
    setmetatable(SubClass, BaseClass);
    SubClass.__index = SubClass;
    SubClass._Base = BaseClass;
    return SubClass;
end

-- 定义单例类
-- anyTableOrNil：待定义的类，可以传nil
-- return: 一个新单例类
-- 通过 class.me() 访问单例
-- 通过重写OnInit()方法指定单例创建时的初始化操作
function SingletonClass(anyTableOrNil)
    anyTableOrNil = DefineClass(anyTableOrNil);
    anyTableOrNil._instance = nil;
    if anyTableOrNil.OnInit == nil then
        anyTableOrNil.OnInit = function(self) end
    end
    anyTableOrNil.me = function()
        if anyTableOrNil._instance == nil then
            anyTableOrNil._instance = true;
            anyTableOrNil:OnInit();
        end
        return anyTableOrNil;
    end
	anyTableOrNil.ResetInstance = function()
		anyTableOrNil._instance = nil;
	end
    return anyTableOrNil;
end

-- 实例化指定类的对象
-- Class：类
-- t: 实例对象，可以是nil
-- return: Class的实例
function New(Class, t)
    t = t or { };
    setmetatable(t, Class);
    return t;
end

-- 修饰或者创建一个只读的table
-- t: 被修饰的类
-- return: 被修饰过的t，此table不能再被更改
function SealedTable(t)
    local temp = t or { }
    local mt =
    {
        __index = function(t, k) return temp[k] end;
        __newindex = function(t, k, v)
            error("attempt to update a read-only table!")
        end
    }
    setmetatable(temp, mt)
    return temp
end

-- 抛出致命异常
-- fmtStr: 异常信息，支持格式化，格式化方式类似C语言
-- 不定参数
function FatalError(fmtStr, ...)
    local str = string.format(fmtStr, ...);
    LuaEntry:FatalError(str);
end

-- 深拷贝（针对table（“引用类型”））
-- object : 待拷贝对象
function DeepCopy(object)
    local lookup_table = { };
    local function _copy(object)
        if type(object) ~= "table" then
            return object;
        elseif lookup_table[object] then
            return lookup_table[object];
        end

        local new_table = { };
        lookup_table[object] = new_table;
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end

    return _copy(object);
end

-- 快速排序
-- array ：待排数据。需支持[]
-- left：排序左起始Index
-- right:排序右起始Index
function QuickSort(array, left, right)
    if left < right then
        local i = left;
        local j = right;
        local x = array[left];
        while i < j do
            while i < j and array[j] >= x do
                -- 从右向左找第一个小于x的数
                j = j - 1;
            end
            if i < j then
                array[i] = array[j];
                i = i + 1;
            end

            while i < j and array[i] < x do
                -- 从左向右找第一个大于等于x的数
                i = i + 1;
            end
            if i < j then
                array[j] = array[i];
                j = j - 1;
            end
        end
        array[i] = x;

        -- 递归调用
        QuickSort(array, left, i - 1);
        QuickSort(array, i + 1, right);
    end
end

--
function SortIf(array, funcObj)
    QuickSortIf(array, 1, #array, funcObj);
end
-- 快速排序If
-- array ：待排数据。需支持[]
-- left：排序左起始Index
-- right:排序右起始Index
-- funcObj: 函数对象，提供array两个元素的比较
-- 示例：funcObj = function(a,b) return a < b end
function QuickSortIf(array, left, right, funcObj)
    if left < right then
        local i = left;
        local j = right;
        local x = array[left];
        while i < j do
            while i < j and(not funcObj(array[j], x)) do
                j = j - 1;
            end
            if i < j then
                array[i] = array[j];
                i = i + 1;
            end

            while i < j and funcObj(array[i], x) do
                i = i + 1;
            end
            if i < j then
                array[j] = array[i];
                j = j - 1;
            end
        end
        array[i] = x;

        -- 递归调用
        QuickSortIf(array, left, i - 1, funcObj);
        QuickSortIf(array, i + 1, right, funcObj);
    end
end

-- Sort小于 （SortIf 协作函数）
-- classNumber： 类的某个字段名（string）
-- return 按照classNumber比较的仿函数
function SortLessThen(classNumber)
    local funcObj = function(left, right)
        return left[classNumber] < right[classNumber];
    end
    return funcObj;
end

-- Sort大于 （SortIf 协作函数）
-- classNumber： 类的某个字段名（string）
-- return 按照classNumber比较的仿函数
function SortLargeThen(classNumber)
    local funcObj = function(left, right)
        return left[classNumber] > right[classNumber];
    end
    return funcObj;
end

-- 在一个table（数组）中查找给定值，并返回它的索引
-- return: 查找失败返回-1
function IndexOf(array, val)
    if array ~= nil then
        for i = 1, #array do
            if array[i] == val then
                return i;
            end
        end
    end
    return -1;
end

-- 查找If
-- array:待查找数组，需支持[]
-- funcObj: IF 函数对象
-- return find 返回第一个符合funcObj的对象。若无符合，返回nil 。
-- return index 返回第一个符合funcObj的对象的下标。若无符合，返回-1。
function FindIf(array, funcObj)
    local find = nil;
    local index = -1;
    if array ~= nil and #array > 0 then
        for i = 1, #array do
            if funcObj(array[i]) then
                find = array[i];
                index = i;
                break;
            end
        end
    end
    return find, index;
end

-- 查找If，函数对象制作函数 （与 FindIf 协作使用）
-- classNumber： 类的某个字段名（string）
-- equalValue ： 类的某个字段 相比较的值
-- 返回函数对象，该函数对象可用于“FindIf”
function FindObject(classNumber, equalValue)
    if classNumber == nil or equalValue == nil then
        print("全局函数FindObject 参数错误，请检查,classNumber=",tostring(classNumber),",equalValue=",tostring(equalValue));
    end

    local funcObj = function(equalValue)
        local checkEqual = function(data)
            return equalValue == data[classNumber];
        end
        return checkEqual;
    end
    return funcObj(equalValue);
end

-- 删除If
-- 删除数组中所有符合funcObj的元素
-- array 目标数组
-- funcObj 匹配funcObj(可使用FindObject)
-- 返回：删除后数组的大小
function RemoveIf(array, funcObj)
    if array == nil or #array == 0 then
        return;
    end
    local ret = {};
    local current = 1;
    for left = 1, #array do
        if not funcObj(array[left]) then
            array[current] = array[left];
            current = current + 1;
        else
            table.insert( ret, array[left]);
        end
        left = left + 1;
    end

    for i = current, #array do
        array[i] = nil;
    end

    return #array, ret;
end

-- 查找有序数组中，第一个大于value的Index
function CheckLargeThenIndex(array, classNumber, value)
    local index = -1;
    for i = 1, #array do
        if array[i][classNumber] > value then
            index = i;
            break;
        end
    end

    return index;
end

--随机洗牌算法
function Random_shuffle( array)
    if array == nil or #array == 0 then
        return;
    end
    for i= #array, 1, -1 do
        local num = Random.Range(1, i+1);
        if num ~= i then
            local temp = array[i];
            array[i] = array[num];
            array[num] = temp;
        end
    end
end

-- 打印Lua table
function print_lua_table(lua_table, indent)
    if lua_table == nil or type(lua_table) ~= "table" then
        return;
    end

    local function print_func(str)
        print("[table value]==>", tostring(str));
    end

    indent = indent or 0;
    for k, v in pairs(lua_table) do
        if type(k) == "string" then
            k = string.format("%q", k);
        end
        local szSuffix = "";
        if type(v) == "table" then
            szSuffix = "{";
        end
        local szPrefix = string.rep(" ", indent);
        formatting = szPrefix .. "[" .. k .. "]" .. " = " .. szSuffix;
        if type(v) == "table" then
            print_func(formatting)
            print_lua_table(v, indent + 1)
            print_func(szPrefix .. "},")
        else
            local szValue = ""
            if type(v) == "string" then
                szValue = string.format("%q", v)
            else
                szValue = tostring(v)
            end
            print_func(formatting .. szValue .. ",")
        end

    end

end

function MergeTable(tableOne, tableTwo)
    local mergeTable = { }
    for index = 1, #tableOne do
        mergeTable[#mergeTable + 1] = tableOne[index];
    end
    for index = 1, #tableTwo do
        mergeTable[#mergeTable + 1] = tableTwo[index];
    end
    return mergeTable;
end

function SmartCall(caller, callback)
    if callback ~= nil then
        if caller ~= nil then
            callback(caller);
        else
            callback();
        end
    end
end

function SmartCallWithArgs(caller, callback, args)
    if callback ~= nil then
        if caller ~= nil then
            callback(caller, args);
        else
            callback(args);
        end
    end
end

function ttt(str)
    if IsLowIOSVer(15) then 
        return str;
    end 
    return LanMgr.Trans(str);
end 



-- 当前是否为IOS系统
function IsIOS()
	return Application.platform == 8;
end

-- 获取当前的版本值
function GetVerCode()
	if IsIOS() then
		local ver = Game.version;
		local notSupportVer = {"1.0.6", "1.0.7", "1.0.8"};
		if IndexOf(notSupportVer, ver) == -1 then
			return Game.verCode;
		else
			return 0;
		end
	else
		return Game.verCode;
	end
end

-- 当前版本是否为IOS的低于verCode版本
-- verCode 版本值
function IsLowIOSVer(verCode)
	return IsIOS() and GetVerCode() < verCode;
end

DebugUtil = {
    Common = "Commmon";
    Family = "Family";
    Team = "Team";
    Panda = "Panda";
    Fun = "Fun";
    Loading = "Loading";
    Mail = "Mail";
    Pet = "Pet";
    Guide = "Guide";
    Login = "Login";
    CreateRole = "CreateRole"
}

function DebugUtil:print(type, ...)
    if type == self.Family then

        --        print("家族消息", ...);
        --    elseif type == self.Team then
        --        print("隊伍消息", ...);
        --    elseif type == self.Panda then
        --        print("测试小熊猫", ...);
    elseif type == self.Fun then
        --        print("测试功能大厅===================================", ...);
    elseif type == self.Loading then
        --        print("测试加载条======================================", ...);
    elseif type == self.Mail then
        --        print("测试邮件======================================", ...);
    elseif type == self.Common then
        --        print("测试======================================", ...);
    elseif type == self.Guide then
        --        print("新手引导测试==================================", ...)
    elseif type == self.Login then
        --        print("Login测试==================================", ...)
    elseif type == self.CreateRole then
        --        print("创角界面测试==================================", ...)
    end
end

